<template>
  <div>
    <div id="mapDiv" style="width: 100vw;height: 100vh;">
    </div>
  </div>
</template>

<script>
// 地图组件
export default {
  name: "MapComponent",
  props: {
    value: { // 从父组件传来的搜索字符
      type: [String, Array],
      default: ''
    }
  },
  data() {
    return {
      map: null,
      distinction: '', // 搜索值
      marker: null,
      Geo: { // 保存选定的地方的坐标信息
        position: [], // 保存地理坐标
        degree: [], // 保存度分秒坐标
      },
    }
  },
  watch: {
    // 120°10'40.195",30°14'46.320"
    // 120.2042181, 30.24775551
    // 114°65'24.6",57°55'56.6"
    // [120.2042181, 30.24775551]
    // [`114°65'24.6"`,`57°55'56.6"`]
    value: function (newVal, oldVal) {
      // 判断输入类型
      if (typeof (newVal) === 'string') { // 字符串
        console.log(newVal)
        if (newVal.indexOf(',') === -1) { // 输入纯字符串
          this.search(newVal)

        } else if (newVal.indexOf('°') !== (-1)) { // 含有度数符号,为度数字符串
          const a = newVal.split(',')
          console.log(a);
          this.calculate(a, 1)
        } else { // 处理纯数字字符串
          const a = newVal.split(',')
          console.log(a);
          const temp = a.map((item) => { // 转为数字
            return Number(item.trim())
          })
          console.log(temp);
          this.calculate(temp, 0)
        }

      } else if (newVal instanceof Array) { // 数组
        console.log(newVal);
        if (newVal[0].toString().indexOf('°') !== -1) { // 第一个元素含有度符号
          console.log(newVal);
          this.calculate(newVal, 1)
        } else {
          console.log(newVal);
          this.calculate(newVal, 0)
        }

      } else {
        console.log('传入参数类型错误,请传入字符串或坐标数组!')
      }

    }
  },
  methods: {
    initMap() {
      let script = document.getElementById('MapDivId');
      if (script) {
        return this._initMap();
      }
      const _this = this;
      script = document.createElement('script');
      script.id = 'MapDivId';
      script.src = 'https://api.tianditu.gov.cn/api?v=4.0&tk=001ef366a77a0f4fb4d8d89f8d72094d'; // 天地图地址
      document.body.appendChild(script); // 添加节点
      script.onload = function () { // 加载节点时的回调
        _this._initMap();
      };

    },
    _initMap() {

      this.map = new T.Map('mapDiv');

      const map = this.map

      map.centerAndZoom(new T.LngLat(120.177832, 30.2462), 12);
      //添加卫星图层，下面这个url是固定的，
      // let satelliteLayerUrl = "http://t0.tianditu.gov.cn/img_w/wmts?" + "SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles" + "&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=001ef366a77a0f4fb4d8d89f8d72094d";
      // let layer = new T.TileLayer(satelliteLayerUrl, { minZoom: 3, maxZoom: 18 });
      // window.GIS.Map = new T.Map('Map', { layers: [layer] });
      // // 定位到一个默认的坐标，例如北京。这里的坐标是虚构的
      // window.GIS.Map.centerAndZoom(new T.LngLat(123.45678, 30.1234), 12);

      map.on('click', (e) => { // 点击添加标志事件
        console.log(e);
        let lnglat = e.lnglat
        this.marker = null // 重置标记对象
        map.clearOverLays() // 清除地图上所有覆盖物

        this.marker = new T.Marker(lnglat); // 创建标志
        this.calculate(lnglat, 0)
        map.addOverLay(this.marker); // 添加标志

        const zoom = map.getZoom(); // 获取当前缩放级别
        map.panTo(lnglat, zoom) // 调整中心点和缩放级别
      })
      // //添加地图类型控件
      let ctrlMapType = new T.Control.MapType([
        {
          title: '卫星混合',
          icon: 'http://api.tianditu.gov.cn/v4.0/image/map/maptype/satellitepoi.png',
          layer: TMAP_HYBRID_MAP
        },
        {
          title: '地图',
          icon: 'http://api.tianditu.gov.cn/v4.0/image/map/maptype/vector.png',
          layer: TMAP_NORMAL_MAP
        }
      ]);
      map.addControl(ctrlMapType);

      // //添加缩放控件
      let ctrlZoom = new T.Control.Zoom();
      this.map.addControl(ctrlZoom);
      ctrlZoom.setPosition(T_ANCHOR_BOTTOM_RIGHT);

      //添加比例尺控件
      let ctrlScale = new T.Control.Scale();
      map.addControl(ctrlScale);
      console.log(map);

    },
    search(value) {
      if (value) { // 值不为空
        const map = this.map
        let marker = this.marker;
        // let position = this.position
        let position = this.Geo.position
        let degree = this.Geo.degree
        const that = this
        let localsearch;
        // 添加搜索
        const config = {
          pageCapacity: 10, // 每页显示的数量
          onSearchComplete: localSearchResult // 接收数据的回调
        }
        // 创建搜索
        localsearch = new T.LocalSearch(map, config)

        localsearch.search(value, 7) //设定搜索值和搜索类型

        // 搜索完成回调
        function localSearchResult(result) {
          console.log(result);

          // const posiStr = result.area.lonlat // 坐标字符串
          const posiStr = result.pois[0].lonlat // 坐标字符串

          let posiArr = [] // 坐标数组
          console.log(posiStr);
          // 将字符串转为数字存到数组中
          const a = posiStr.split(' ')

          a.map((item, index) => {

            let tem = Number(item)

            posiArr.push(tem)
          })
          console.log(posiArr);
          position = posiArr // 保存坐标
          degree = that.calculate(posiArr,0) // 保存坐标

          that.$emit('sendPosi',that.Geo) // 发送事件

          marker = null; // 重置标记对象
          map.clearOverLays() // 清除地图上所有覆盖物
          const lnglat = new T.LngLat(posiArr[0], posiArr[1]);
          marker = new T.Marker(lnglat); // 创建标志
          map.addOverLay(marker); // 添加标志

          // map.setViewport(120.2042181, 30.24775551) // 调整视野,没用?
          const zoom = map.getZoom() // 获取当前缩放级别
          map.panTo(lnglat, zoom) // 调整中心点和缩放级别
        }

      }
    },
    submit() {
      this.search(this.distinction)
    },
    zoom() { // 测试缩放
      const map = this.map

      const arr = [120.2042181, 30.24775551];
      const a = new T.LngLat(arr[0], arr[1])
      // console.log(a);
      map.panTo(a, 10) // 第一个参数需要传入对象数组
      // map.setViewport({lat:120.2042181,lng: 30.24775551})

      const b = map.lngLatToLayerPoint(a) // 将地理坐标转化为地图图层上点的像素坐标
      console.log(b);
      const c = map.lngLatToContainerPoint(a)// 将地理坐标转化为地图上点的像素坐标
      console.log(c)
    },
    createMarker(posiObj) { // 创建由传递参数所需创建的标记
      console.log(posiObj)
      this.marker = null // 重置标记对象

      this.map.clearOverLays() // 清除地图上所有覆盖物

      this.marker = new T.Marker(posiObj); // 创建标志

      this.map.addOverLay(this.marker); // 添加标志

      const zoom = this.map.getZoom(); // 获取当前缩放级别
      this.map.panTo(posiObj, zoom) // 调整中心点和缩放级别
    },
    calculate(param, num) { // 计算度分秒坐标

      let temp; // 临时数组,保存坐标
      let result;  // 保存及计算的坐标数组

      switch (num) {
        case 0 : // 参数为0,由经纬度计算度分秒坐标
          if (!param.length) { // 参数是对象
            console.log(param)
            temp = [param.lng, param.lat] // 临时数组
            this.Geo.position = temp // 保存坐标数组
            result = calculateGeo(temp) // 计算度分秒坐标
            this.Geo.degree = result // 保存坐标
            this.$emit('sendPosi',this.Geo) // 发送事件
            console.log(this.Geo)
          } else if (param instanceof Array) { // 参数是数组

            temp = param
            console.log(param);
            this.Geo.position = temp
            result = calculateGeo(param)
            this.Geo.degree = result
            this.$emit('sendPosi',this.Geo) // 发送事件
            this.createMarker({lon: param[0], lat: param[1]}) // 传递的数组创建的标记
            console.log(this.Geo)
          } else {
            console.log('参数类型错误!')
          }
          break;
        case 1: // 参数为1,由度分秒计算经纬度坐标

          // 由度分秒数组绘制标记

          result = calculateDegree(param) // 转化好的经纬度数组

          this.createMarker({lng: result[0], lat: result[1]})

          this.Geo.position = result
          this.Geo.degree = param
          this.$emit('sendPosi',this.Geo) // 发送事件
          console.log(this.Geo)
          break;
      }

      function calculateGeo(lonlatArr) { // 经纬度转为度分秒

        // 示例: lonlatArr=[116.41661560068297, 39.92196580126834]
        console.log(lonlatArr);
        let result = []
        lonlatArr.forEach((item) => {

          let str = item.toString();
          const int = str.split('.')[0] // 获取整数部分
          const decimal1 = '0.' + str.split('.')[1] // 获取第一个小数部分
          const num = (Number(decimal1) * 60).toFixed(6) // 获取分钟数和小数
          const minute = Math.floor(Number(num)) // 获取分钟
          const decimal2 = '0.' + num.toString().split('.')[1] // 获取第二个小数
          const second = (Number(decimal2) * 60).toFixed(3) // 获取秒
          const resStr = int + `°` + minute.toString() + `\'` + second.toString() + `"`
          result.push(resStr)
        })
        // console.log(result)
        return result
      }

      function calculateDegree(degreeArr) { // 度分秒转经纬度
        console.log(degreeArr);
        // 示例: degreeArr=['114°65\'24.6','57°55\'56.6']
        const result = []
        degreeArr.forEach((item) => {

          let str = item.toString();
          const degree = str.split('°')[0]// 度
          const minute = str.split('\'')[0].split('°')[1] // 分
          const length = str.split('\'')[1].length // 秒的长度
          const second = str.split('\'')[1].substring(0, length - 1) // 截取到秒
          const res = (Number(degree) + Number(minute) / 60 + Number(second) / 3600).toFixed(6) // 相加获取最终坐标

          result.push(res)
        })
        return result
      }
      return result
    }
  },

  mounted() {
    this.initMap()
  }
}
</script>

<style scoped>

</style>
